package com.hwtx.form.domain.handle.formconfig;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hwtx.form.annotation.FormType;
import com.hwtx.form.domain.def.FormConfigExt;
import com.hwtx.form.domain.def.FormDef;
import com.hwtx.form.domain.def.FormDetailExt;
import com.hwtx.form.domain.def.meta.config.FormComponentConfig;
import com.hwtx.form.domain.ds.DataSourceContextHolder;
import com.hwtx.form.domain.handle.FormDataHandle;
import com.hwtx.form.domain.handle.datamodel.DataModel;
import com.hwtx.form.domain.handle.datamodel.DataModelDetail;
import com.hwtx.form.domain.handle.datamodel.DataModelRelate;
import com.hwtx.form.domain.listener.EventPublisher;
import com.hwtx.form.domain.listener.FormConfigChangeEvent;
import com.hwtx.form.domain.repo.DataModelRepo;
import com.hwtx.form.domain.repo.FormConfigRepo;
import com.hwtx.form.domain.repo.FormRepo;
import com.hwtx.form.domain.service.ResourceService;
import com.hwtx.form.domain.vo.*;
import com.hwtx.form.dto.FormListQuery;
import com.hwtx.form.persistence.DataSourceRepo;
import com.hwtx.form.persistence.entity.FormConfigQuery;
import com.hwtx.form.persistence.entity.FormDefDetail;
import com.hwtx.form.query.FormValueQuery;
import io.geekidea.boot.auth.cache.LoginCache;
import io.geekidea.boot.framework.exception.BusinessException;
import io.geekidea.boot.framework.page.Paging;
import io.geekidea.boot.system.query.SysMenuQuery;
import jakarta.annotation.Resource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.stream.Streams;
import org.jetbrains.annotations.NotNull;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

import static com.hwtx.form.domain.FormConstants.*;
import static com.hwtx.form.domain.FormConstants.FormLayout.LAYOUT_0;
import static com.hwtx.form.domain.def.meta.config.FormComponentConfig.getFormComponentConfig;
import static com.hwtx.form.util.FormUtil.*;
import static com.hwtx.form.util.JacksonUtil.*;

@FormType(value = FORM_CONFIG_HANDLE_NAME, comment = "表单配置", actionClass = FormConfigAction.class)
@Slf4j
public class FormConfigDataHandle implements FormDataHandle {

    final List<Integer> configTypeDetails = Lists.newArrayList(FormConfigType.QUERY.getValue(), FormConfigType.FORM.getValue(), FormConfigType.LIST.getValue());
    @Resource
    private FormConfigRepo formConfigRepo;
    @Resource
    private FormRepo formRepo;
    @Resource
    private DataSourceRepo dataSourceRepo;
    @Resource
    private DataModelRepo dataModelRepo;
    @Resource
    private ResourceService resourceService;
    @Resource
    private EventPublisher eventPublisher;
    @Resource
    private FormTplHandle formTplHandle;

    @Override
    public Paging<?> page(FormDef formDef, FormListQuery formListQuery) {
        if (formListQuery.getSearchPostData().get(SHORT_FORM_ID) == null || StringUtils.isBlank(formListQuery.getSearchPostData().get(SHORT_FORM_ID).toString())) {
            throw new BusinessException("表单ID不能为空");
        }
        if (formListQuery.getSearchPostData().get("type") == null || StringUtils.isBlank(formListQuery.getSearchPostData().get("type").toString())) {
            throw new BusinessException("明细类型不能为空");
        }
        String type = formListQuery.getSearchPostData().get("type").toString();
        if (formListQuery.getSearchPostData().get("modelName") == null || StringUtils.isBlank(formListQuery.getSearchPostData().get("modelName").toString())) {
            throw new BusinessException("请选择数模型");
        }
        switch (type) {
            case QUERY, FORM -> {
                return queryFormQuery(type, formListQuery);
            }
            case LIST -> {
                return queryFormList(formListQuery);
            }
        }
        return new Paging<>(Lists.newArrayList());
    }

    private QueryRet queryFormConfig(String type, FormListQuery formListQuery, QueryConfigCallback queryConfigCallback) {
        String fId = getStrPostValue(formListQuery.getSearchPostData(), SHORT_FORM_ID);
        QueryRet queryRet = new QueryRet();
        if (fId != null) {
            Long formId = Long.valueOf(fId);
            FormDefDetail formDetail = formConfigRepo.getFormDetail(formId);
            if (formDetail == null) {
                queryRet.setData(new Paging<>(Lists.newArrayList(), 0, formListQuery.getPageIndex(), formListQuery.getPageSize()));
                return queryRet;
            }
            if (Objects.equals(type, FORM)) {
                FormDetailExt formDetailExt = getFormDetailExt(formDetail.getExt());
                if (formDetailExt != null && formDetailExt.getFormExt() != null) {
                    queryRet.setFormStatic(formDetailExt.getFormExt().getFormStatic());
                }
            }
            String modelName = getStrPostValue(formListQuery.getSearchPostData(), "modelName");
            if (modelName == null) {
                throw new BusinessException("请选择数模型");
            }
            DataModel dataModel = dataModelRepo.getDataModel(modelName);
            List<DataModelRelate> relates = dataModelRepo.getRelates(modelName);
            String master = dataModel.getMaster();
            String ds = dataModel.getDs();
            String dsKey = DataSourceContextHolder.getDataSourceKey();
            DataSourceContextHolder.checkDataSourceKey(ds);
            try {
                if (!dataSourceRepo.exist(master)) {
                    throw new BusinessException("数模型【" + dataModel.getModelName() + "】不存在");
                }
                if (CollectionUtils.isNotEmpty(relates)) {
                    for (DataModelRelate relate : relates) {
                        if (!dataSourceRepo.exist(relate.getFirstName())) {
                            throw new BusinessException("数模表【" + relate.getFirstName() + "】不存在");
                        }
                        if (!dataSourceRepo.exist(relate.getSecondName())) {
                            throw new BusinessException("数模表【" + relate.getSecondName() + "】不存在");
                        }
                    }
                }
            } finally {
                DataSourceContextHolder.setDataSourceKey(dsKey);
            }
            if (Objects.equals(dataModel.getModelName(), formDetail.getModelName())) {
                List<DataModelDetail> dataModelDetails = dataModelRepo.getDetails(modelName, Status.VALID);
                String name = getStrPostValue(formListQuery.getSearchPostData(), "name");
                Paging<FormConfigQueryVo> ret = queryConfigCallback.list(dataModel, formId, name);
                queryRet.setData(ret);
                queryRet.setInit(StringUtils.isNotBlank(name) || dataModelDetails.size() == ret.getTotal());
            }
        }
        return queryRet;
    }

    private Paging<FormConfigQueryVo> queryFormList(FormListQuery formListQuery) {
        AtomicReference<String> tableType = new AtomicReference<>();
        AtomicReference<String> warning = new AtomicReference<>("");
        QueryRet queryRet = queryFormConfig(LIST, formListQuery, (dataModel, formId, name) -> {
            tableType.set(dataModel.getTableType());
            Paging<FormConfigQueryVo> ret = formConfigRepo.pageMergedFormConfig(formListQuery.getPageIndex(), formListQuery.getPageSize(), FormConfigQuerySearchVo.builder().formId(formId).name(name).build());
            String master = dataModel.getMaster();
            ret.setItems(ret.getItems().stream().peek(vo -> {
                vo.setFormId(null);
                if (Objects.equals(DefaultColumn.id.name(), vo.getField())) {
                    if (Objects.equals(vo.getTableName(), master)) {
                        if (vo.getIsListQuery() == (byte) 0) {
                            warning.set("请将【" + master + "." + DefaultColumn.id.name() + "】字段设置为列表查询字段,关联表【" + vo.getDescription() + "】无需查询");
                        }
                    } else {
                        if (vo.getIsListQuery() == (byte) 1) {
                            warning.set("请将【" + vo.getTableName() + "." + DefaultColumn.id.name() + "】字段取消列表查询");
                        }
                    }
                }


            }).toList());
            return ret;
        });
        queryRet.setWarning(warning.get());
        return getFormConfigQueryVoPaging(tableType, queryRet);
    }

    private Paging<FormConfigQueryVo> queryFormQuery(String type, FormListQuery formListQuery) {
        AtomicReference<String> tableType = new AtomicReference<>();
        AtomicReference<String> warning = new AtomicReference<>("");
        QueryRet queryRet = queryFormConfig(type, formListQuery, (dataModel, formId, name) -> {
            tableType.set(dataModel.getTableType());
            Paging<FormConfigQueryVo> ret = formConfigRepo.pageMergedFormConfig(formListQuery.getPageIndex(), formListQuery.getPageSize(), FormConfigQuerySearchVo.builder().formId(formId).name(name).build());
            AtomicReference<String> tableName = new AtomicReference<>();
            if (!DataModel.isAggTableModel(dataModel.getTableType())) {
                tableName.set(ret.getItems().stream().map(FormConfigQueryVo::getTableName).filter(StringUtils::isNotEmpty).distinct().findFirst().orElse(null));
            }
            ret.setItems(ret.getItems().stream().peek(vo -> {
                if (StringUtils.isEmpty(vo.getField())) {
                    vo.setTableName(tableName.get());
                }
                if (Objects.equals(type, FORM)) {
                    if (Objects.equals(DefaultColumn.id.name(), vo.getField())) {
                        if (!Objects.equals(vo.getFormController(), FormComponentType.FORM_COM_HIDDEN.getValue())) {
                            warning.set("请将【" + vo.getTableName() + "." + DefaultColumn.id.name() + "】字段设置为隐藏字段");
                        }
                    }
                    if (Objects.equals(vo.getIsFormShow(), (byte) 1) && vo.getFormController() == null) {
                        warning.set("请为【" + vo.getTableName() + "." + vo.getField() + "】字段设置组件");
                    }
                } else if (Objects.equals(type, QUERY)) {
                    if (Objects.equals(vo.getIsQueryShow(), (byte) 1) && vo.getQueryController() == null) {
                        warning.set("请为【" + vo.getTableName() + "." + vo.getField() + "】字段设置组件");
                    }
                }
            }).toList());
            return ret;
        });
        queryRet.setWarning(warning.get());
        return getFormConfigQueryVoPaging(tableType, queryRet);
    }

    @NotNull
    private Paging<FormConfigQueryVo> getFormConfigQueryVoPaging(AtomicReference<String> tableType, QueryRet queryRet) {
        Paging<FormConfigQueryVo> ret = queryRet.getData();
        Map<String, Object> map = Maps.newHashMap();
        map.put("tableType", tableType.get());
        map.put("init", queryRet.isInit());
        map.put("formStatic", queryRet.getFormStatic());
        map.put("warning", queryRet.getWarning());
        ret.setUData(map);
        return ret;
    }

    @Override
    public FormRepData getFormData(FormDef formDef, FormValueQuery formValueQuery) {
        Long queryId = formValueQuery.getValueIds().getFirst();
        if (Objects.equals(formValueQuery.getType(), "detail")) {
            Map<String, Object> ret = Maps.newHashMap();
            FormDefDetail formDefDetail = formConfigRepo.getFormDetail(formValueQuery.getFId());
            if (formDefDetail != null) {
                ret = object2Map(formDefDetail);
            }
            return FormRepData.builder().data(ret).build();
        } else if (Objects.equals(formValueQuery.getType(), "formExt") || Objects.equals(formValueQuery.getType(), "tplExt")) {
            return FormRepData.builder().data(getFormDefDetailExt(formValueQuery.getFId(), formValueQuery.getType())).build();
        }
        return FormRepData.builder().data(getFormConfigItemExt(queryId, formValueQuery.getType())).build();
    }

    private Object getFormDefDetailExt(Long formId, String type) {
        FormDefDetail formDefDetail = formConfigRepo.getFormDetail(formId);
        if (formDefDetail == null) {
            return null;
        }
        if (type.equals("tplExt")) {
            return formTplHandle.getTplConfig(formId);
        }
        FormDetailExt ext = getFormDetailExt(formDefDetail.getExt());
        if (ext != null) {
            if (type.equals("formExt")) {
                return ext.getFormExt();
            }
        }
        return null;
    }

    private Object getFormConfigItemExt(Long id, String type) {
        FormConfigQuery formConfigQuery = formConfigRepo.getFormConfigQuery(id);
        Map<String, Object> ret = Maps.newHashMap();
        FormConfigExt ext = getFormConfigExt(formConfigQuery.getExt());
        Integer controller = null;
        switch (type) {
            case QUERY -> controller = formConfigQuery.getQueryController();
            case FORM -> controller = formConfigQuery.getFormController();
            case LIST -> controller = formConfigQuery.getListController();
        }
        if (ext != null) {
            switch (type) {
                case QUERY -> buildExt(ext.getQuery(), ret, controller);
                case FORM -> buildExt(ext.getForm(), ret, controller);
                case LIST -> buildExt(ext.getList(), ret, controller);
            }
            FormComponentConfig formComponentConfig = getFormComponentConfig(controller);
            if (formComponentConfig != null) {
                FormComponentConfig.OutputConfig outputConfig = formComponentConfig.getOutputConfigParams(type, getFormConfigCtr(type, ext));
                if (outputConfig != null) {
                    if (CollectionUtils.isNotEmpty(outputConfig.getNotIncludeKeys())) {
                        outputConfig.getNotIncludeKeys().forEach(ret::remove);
                    }
                    if (outputConfig.getParams() != null) {
                        ret.putAll(outputConfig.getParams());
                    }
                }
            }
        } else {
            FormConfigExt.FormConfigCtr formConfigCtr = new FormConfigExt.FormConfigCtr();
            formConfigCtr.setCtrType(controller);
            ret.putAll(object2Map(formConfigCtr));
        }
        ret.put("description", formConfigQuery.getDescription());
        ret.put("name", formConfigQuery.getName());
        ret.put("num", formConfigQuery.getNum());
        return ret;
    }

    private void buildExt(FormConfigExt.BaseConfig baseConfig, Map<String, Object> ret, Integer controller) {
        if (baseConfig != null) {
            if (baseConfig.getConfigCtr() == null) {
                if (controller != null) {
                    FormConfigExt.FormConfigCtr ctr = new FormConfigExt.FormConfigCtr();
                    ctr.setCtrType(controller);
                    ret.putAll(object2Map(ctr));
                } else {
                    ret.putAll(FormConfigExt.FormConfigCtr.emptyMap());
                }
            } else {
                baseConfig.getConfigCtr().setCtrType(controller);
                ret.putAll(object2Map(baseConfig.getConfigCtr()));
            }
            ret.putAll(object2Map(baseConfig));
        } else {
            if (controller != null) {
                FormConfigExt.FormConfigCtr ctr = new FormConfigExt.FormConfigCtr();
                ctr.setCtrType(controller);
                ret.putAll(object2Map(ctr));
            } else {
                ret.putAll(FormConfigExt.FormConfigCtr.emptyMap());
            }
        }
    }

    @Override
    @Transactional
    public Object removeFormData(FormDef formDef, FormValueQuery formValueQuery) {
        if (Objects.equals(formValueQuery.getType(), "detail")) {
            formConfigRepo.deleteFormConfigQueryById(formValueQuery.getValueIds().getFirst());
            return true;
        }
        formConfigRepo.deleteFormConfigQuery(formDef.getFormId());
        formConfigRepo.deleteFormDetail(formDef.getFormId());
        formDef.setConfig(false);
        SysMenuQuery sysMenu = new SysMenuQuery();
        sysMenu.setFId(formDef.getFormId());
        resourceService.getPermissions(sysMenu).forEach(permission -> resourceService.deleteSysMenu(permission.getId()));
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object saveFormData(FormDef formDef, FormData formData) {
        String type = getStrPostValue(formData.getData(), "type");
        Long formId = getLongPostValue(formData.getData(), SHORT_FORM_ID);
        if (formId == null) {
            throw new BusinessException("表单ID不能为空");
        }
        boolean suc;
        suc = switch (type) {
            case "ext" -> saveDetailExt(formId, formData);
            case "detail" -> saveFormDetail(formId, formData);
            case QUERY, LIST ->
                    saveFormDataInternal(formId, formData, type, (formConfigCtr, existFormConfigExt, formConfigQuery, existFormConfigQuery) -> {
                        FormConfigExt.QueryConfig listConfig = map2Oject(formData.getData(), FormConfigExt.QueryConfig.class);
                        if (!formConfigCtr.empty()) {
                            if (Objects.equals(type, QUERY)) {
                                formConfigQuery.setQueryController(formConfigCtr.getCtrType());
                            } else {
                                formConfigQuery.setListController(formConfigCtr.getCtrType());
                            }
                            formConfigCtr.setCtrType(null);
                        }
                        if (!listConfig.empty()) {
                            DataModelDetail dataModelDetail = dataModelRepo.getDetail(existFormConfigQuery.getModelDetailId());
                            FormConfigExt.SearchConfig searchConfig = listConfig.getSearch();
                            if (searchConfig != null && StringUtils.isNotBlank(searchConfig.getOperator())) {
                                if (StringUtils.isEmpty(searchConfig.getAlias())) {
                                    throw new RuntimeException("搜索别名不能为空");
                                }
                                searchConfig.setProperty(dataModelDetail.getName());
                                listConfig.setSearch(searchConfig);
                            } else {
                                listConfig.setSearch(null);
                            }
                            if (!formConfigCtr.empty()) {
                                listConfig.setConfigCtr(formConfigCtr);
                            }
                            if (type.equals(LIST)) {
                                existFormConfigExt.setList(listConfig);
                            } else {
                                existFormConfigExt.setQuery(listConfig);
                            }
                        } else {
                            if (!formConfigCtr.empty()) {
                                listConfig.setConfigCtr(formConfigCtr);
                                if (type.equals(LIST)) {
                                    existFormConfigExt.setList(listConfig);
                                } else {
                                    existFormConfigExt.setQuery(listConfig);
                                }
                            }
                        }
                    });
            case FORM ->
                    saveFormDataInternal(formId, formData, type, (formConfigCtr, existFormConfigExt, formConfigQuery, existFormConfigQuery) -> {
                        FormConfigExt.FormConfig formConfig = map2Oject(formData.getData(), FormConfigExt.FormConfig.class);
                        if (!formConfigCtr.empty()) {
                            formConfigQuery.setFormController(formConfigCtr.getCtrType());
                            formConfigCtr.setCtrType(null);
                            formConfig.setConfigCtr(formConfigCtr);
                        }
                        if (!formConfig.empty()) {
                            existFormConfigExt.setForm(formConfig);
                        }
                    });
            case null, default -> throw new BusinessException("未知类型");
        };
        eventPublisher.publishEvent(new FormConfigChangeEvent(this, formId));
        updateFormDefConfigStatus(formId);
        return suc;
    }

    private Map<String, Object> handleFormConfigCtrExt(Integer ctrType, FormData formData, FormConfigExt.FormConfigCtr existFormConfigCtr) {
        FormComponentConfig formComponentConfig = getFormComponentConfig(ctrType);
        Map<String, Object> comExt = null;
        if (formComponentConfig != null) {
            if (existFormConfigCtr != null) {
                comExt = existFormConfigCtr.getComExt();
            }
            if (comExt == null) {
                comExt = Maps.newHashMap();
            }
            Map<String, Object> inputConfigParams = formComponentConfig.getInputConfigParams(comExt, formData);
            if (MapUtils.isEmpty(inputConfigParams)) {
                log.warn("Input config params is empty,controller type:{}", ctrType);
            }
            return inputConfigParams;
        }
        return null;
    }

    private boolean saveDetailExt(Long formId, FormData formData) {
        FormDefDetail exist = formConfigRepo.getFormDetail(formId);
        if (exist == null) {
            throw new BusinessException("请先保存表单明细");
        }
        if (exist.getTpl() == null) {
            throw new BusinessException("请先选择模板");
        }
        FormDetailExt ext = getFormDetailExt(exist.getExt());
        if (ext == null) {
            ext = new FormDetailExt();
        }
        FormLayout formLayout = FormLayout.of(exist.getTpl());
        if (!Objects.equals(formLayout, LAYOUT_0)) {
            return formTplHandle.saveTplConfig(formId, formLayout, formData.getData());
        } else {
            if (Objects.equals(formData.getData().get("subType"), "list")) {
                FormDetailExt.ListExt listExt = map2Oject(formData.getData(), FormDetailExt.ListExt.class);
                if (listExt != null) {
                    if (MapUtils.isEmpty(listExt.getParamMapping())) {
                        listExt.setParamMapping(null);
                    }
                    if (ext.getConfigTabs().contains(FormConfigType.QUERY.getValue().toString()) && listExt.getOperations() != null) {
                        boolean hasSearchExt = listExt.getOperations().stream().anyMatch(op -> Objects.equals(op.getValue(), OPERATION_SEARCH));
                        if (hasSearchExt) {
                            throw new BusinessException("已设置查询配置，无需添加搜索扩展");
                        }
                    }
                    ext.setListExt(listExt);
                }
            } else if (Objects.equals(formData.getData().get("subType"), "form")) {
                FormDetailExt.FormExt formExt = map2Oject(formData.getData(), FormDetailExt.FormExt.class);
                if (formExt != null) {
                    if (MapUtils.isNotEmpty(formExt.getParamMapping())) {
                        DataModel dataModel = dataModelRepo.getDataModel(exist.getModelName());
                        if (formExt.getParamMapping().keySet().stream().anyMatch(column -> !containColumn(dataModel, column))) {
                            throw new BusinessException("表单参数映射的列不存在,参数 = " + object2json(formExt.getParamMapping().keySet()));
                        }
                    } else {
                        formExt.setParamMapping(null);
                    }
                    ext.setFormExt(formExt);
                }
            }
        }
        exist.setExt(object2json(ext));
        exist.setUpdateTime(new Date());
        exist.setUpdateId(LoginCache.get().getUsername());
        return formConfigRepo.updateFormDefDetail(exist) > 0;
    }

    private boolean saveFormDetail(Long formId, FormData formData) {
        FormDefDetail formDefDetail = map2Oject(formData.getData(), FormDefDetail.class);
        assert formDefDetail != null;
        formDefDetail.setFormId(formId);
        FormDefDetail exist = formConfigRepo.getFormDetail(formId);
        if (formDefDetail.getTpl() == null) {
            throw new BusinessException("请先选择模板");
        }
        if (StringUtils.isNotBlank(formDefDetail.getKeyId()) && formDefDetail.getKeyId().contains("_")) {
            throw new BusinessException("标识不能包含下划线");
        }
        boolean suc;
        FormDetailExt ext = handleConfigTabs(formId, formData, exist);
        if (ext != null) {
            formDefDetail.setExt(object2json(ext));
        }
        if (exist == null) {
            suc = formConfigRepo.saveFormDefDetail(formDefDetail) > 0;
        } else {
            if (formDefDetail.getTpl().equals(LAYOUT_0.getCode())) {
                if (!Objects.equals(formDefDetail.getModelName(), exist.getModelName())) {
                    formConfigRepo.deleteFormConfigQuery(formId);
                }
            }
            formDefDetail.setUpdateTime(new Date());
            formDefDetail.setUpdateId(LoginCache.get().getUsername());
            suc = formConfigRepo.updateFormDefDetail(formDefDetail) > 0;
        }
        return suc;
    }

    private FormDetailExt handleConfigTabs(Long formId, FormData formData, FormDefDetail exist) {
        String configTabs = (String) formData.getData().get("configTabs");

        if (StringUtils.isBlank(configTabs)) {
            return null;
        }
        List<Integer> comingConfigs = Arrays.stream(configTabs.split(",")).map(Integer::parseInt).sorted(Comparator.comparing(Integer::valueOf)).toList();
        boolean configChange = false;
        FormDetailExt formDetailExt = new FormDetailExt();
        formDetailExt.setConfigTabs(configTabs);
        if (exist != null) {
            FormDetailExt existExt = getFormDetailExt(exist.getExt());
            if (existExt != null) {
                if (StringUtils.isNotBlank(existExt.getConfigTabs())) {
                    List<Integer> existConfigs = Arrays.stream(existExt.getConfigTabs().split(",")).map(Integer::parseInt).sorted(Comparator.comparing(Integer::valueOf)).toList();
                    configChange = !CollectionUtils.isEqualCollection(existConfigs, comingConfigs);
                } else {
                    configChange = true;
                }
                existExt.setConfigTabs(configTabs);
                formDetailExt = existExt;
            }
        } else {
            configChange = true;
        }
        if (!configChange) {
            return null;
        }
        FormConfigQuery formConfigQuery = new FormConfigQuery();
        Collection<Integer> subCollection = CollectionUtils.subtract(configTypeDetails, comingConfigs);
        comingConfigs.forEach(tab -> {
            if (Objects.equals(tab, FormConfigType.QUERY.getValue())) {
                formConfigQuery.setIsQueryShow((byte) 1);
            } else if (Objects.equals(tab, FormConfigType.FORM.getValue())) {
                formConfigQuery.setIsFormShow((byte) 1);
            } else if (Objects.equals(tab, FormConfigType.LIST.getValue())) {
                formConfigQuery.setIsListShow((byte) 1);
                formConfigQuery.setIsListQuery((byte) 1);
            }
        });
        subCollection.forEach(tab -> {
            if (Objects.equals(tab, FormConfigType.QUERY.getValue())) {
                formConfigQuery.setIsQueryShow((byte) 0);
            } else if (Objects.equals(tab, FormConfigType.FORM.getValue())) {
                formConfigQuery.setIsFormShow((byte) 0);
            } else if (Objects.equals(tab, FormConfigType.LIST.getValue())) {
                formConfigQuery.setIsListShow((byte) 0);
                formConfigQuery.setIsListQuery((byte) 0);
            }
        });
        formConfigRepo.updateFormConfigQueryListFormQueryShowStatus(formId, formConfigQuery);
        return formDetailExt;
    }

    public void updateFormDefConfigStatus(Long formId) {
        try {
            final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            FormDef formDef = formRepo.getFormDef(formId);
            formDef.setConfig(true);
            formDef.setUpdateTime(sdf.format(new Date()));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private boolean saveFormDataInternal(Long formId, FormData formData, String type, SaveFormQueryConfigCallback callback) {
        FormConfigQuery formConfigQuery = map2Oject(formData.getData(), FormConfigQuery.class);
        formConfigQuery.setFormId(formId);
        if (formConfigQuery.getNum() != null || StringUtils.isNotEmpty(formConfigQuery.getName())) {
            List<FormConfigQuery> configs = formConfigRepo.listFormConfigQuery(FormConfigQuerySearchVo.builder().formId(formConfigQuery.getFormId()).num(formConfigQuery.getNum()).name(formConfigQuery.getName()).build());
            if (!configs.isEmpty()) {
                if (!(configs.size() == 1 && Objects.equals(configs.getFirst().getId(), formConfigQuery.getId()))) {
                    throw new BusinessException("编号或名称重复");
                }
            }
        }
        FormConfigType formConfigType = FormConfigType.of(type);
        //表单配置中如何不是组件，但配置了隐藏组件，需要该字段来自于dataModel，并且具备默认值
        if (Objects.equals(formConfigType, FormConfigType.FORM) && StringUtils.isEmpty(formConfigQuery.getName())) {
            if (formConfigQuery.getFormController() != null && formConfigQuery.getFormController() == FormComponentType.FORM_COM_HIDDEN.getValue()) {
                FormDefDetail formDefDetail = formConfigRepo.getFormDetail(formId);
                if (StringUtils.isNotEmpty(formDefDetail.getModelName())) {
                    if (formConfigQuery.getId() != null) {
                        FormConfigQuery temp = formConfigRepo.getFormConfigQuery(formConfigQuery.getId());
                        List<DataModelDetail> details = dataModelRepo.getDetails(DataModelDetailQuery.builder().modelName(formDefDetail.getModelName()).build());
                        if (details.stream().anyMatch(detail -> detail.getId().equals(temp.getModelDetailId()) && detail.getPriKey() != (byte) 1 && StringUtils.isEmpty(detail.getDefValue()))) {
                            throw new BusinessException("非主键的隐藏字段需要默认值");
                        }
                    }
                }
            }
        }
        if (formConfigQuery.getId() == null) {
            String ctrType = getStrPostValue(formData.getData(), "ctrType");
            switch (formConfigType) {
                case QUERY -> {
                    formConfigQuery.setIsQueryShow((byte) 1);
                    if (StringUtils.isNotBlank(ctrType)) {
                        formConfigQuery.setQueryController(Integer.parseInt(ctrType));
                    }
                }
                case FORM -> {
                    formConfigQuery.setIsFormShow((byte) 1);
                    if (StringUtils.isNotBlank(ctrType)) {
                        formConfigQuery.setFormController(Integer.parseInt(ctrType));
                    }
                }
                case LIST -> {
                    formConfigQuery.setIsListShow((byte) 1);
                    if (StringUtils.isNotBlank(ctrType)) {
                        formConfigQuery.setListController(Integer.parseInt(ctrType));
                    }
                }
            }
            formConfigRepo.saveFormConfigQuery(formConfigQuery);
            return true;
        }
        String ids = getStrPostValue(formData.getData(), "ids");
        if (StringUtils.isNotBlank(ids)) {
            batSaveFormOrQuery(formData, type);
            return true;
        }
        FormConfigExt.FormConfigCtr formConfigCtr = map2Oject(formData.getData(), FormConfigExt.FormConfigCtr.class);
        FormConfigQuery existFormConfigQuery = formConfigRepo.getFormConfigQuery(formConfigQuery.getId());
        if (existFormConfigQuery == null) {
            throw new BusinessException("表单配置项不存在，Id= " + formConfigQuery.getId());
        }
        FormConfigExt existFormConfigExt = getFormConfigExt(existFormConfigQuery.getExt());
        if (existFormConfigExt == null) {
            existFormConfigExt = new FormConfigExt();
        }
        Integer ctrType = formConfigCtr.getCtrType();
        FormConfigExt.FormConfigCtr existFormConfigCtr = getFormConfigCtr(type, existFormConfigExt);
        formConfigCtr.setComExt(handleFormConfigCtrExt(ctrType, formData, existFormConfigCtr));
        callback.handleExt(formConfigCtr, existFormConfigExt, formConfigQuery, existFormConfigQuery);
        switch (type) {
            case QUERY -> {
                formConfigQuery.setFormController(existFormConfigQuery.getFormController());
                formConfigQuery.setListController(existFormConfigQuery.getListController());
                if (formConfigQuery.getQueryController() == null && existFormConfigExt.getQuery() != null && existFormConfigExt.getQuery().getConfigCtr() != null) {
                    existFormConfigExt.getQuery().getConfigCtr().setCtrType(null);
                }
            }
            case FORM -> {
                formConfigQuery.setQueryController(existFormConfigQuery.getQueryController());
                formConfigQuery.setListController(existFormConfigQuery.getListController());
                if (formConfigQuery.getFormController() == null && existFormConfigExt.getForm() != null && existFormConfigExt.getForm().getConfigCtr() != null) {
                    existFormConfigExt.getForm().getConfigCtr().setCtrType(null);
                }
            }
            case LIST -> {
                formConfigQuery.setQueryController(existFormConfigQuery.getQueryController());
                formConfigQuery.setFormController(existFormConfigQuery.getFormController());
                if (formConfigQuery.getListController() == null && existFormConfigExt.getList() != null && existFormConfigExt.getList().getConfigCtr() != null) {
                    existFormConfigExt.getList().getConfigCtr().setCtrType(null);
                }
            }
        }
        formConfigQuery.setExt(existFormConfigExt.exist() ? object2json(existFormConfigExt) : null);
        formConfigQuery.setFormId(null);
        formConfigQuery.setUpdateTime(new Date());
        formConfigQuery.setUpdateId(LoginCache.get().getUsername());
        return formConfigRepo.updateFormConfigQuery(formConfigQuery) > 0;
    }

    private void batSaveFormOrQuery(FormData formData, String type) {
        List<Integer> ids = Streams.of(formData.getData().get("ids").toString().split(",")).map(Integer::parseInt).toList();
        if (QUERY.equals(type)) {
            FormConfigQuerySearchVo searchVo = FormConfigQuerySearchVo.builder().ids(ids).build();
            FormConfigQuery formConfigQuery = map2Oject(formData.getData(), FormConfigQuery.class);
            formConfigRepo.listFormConfigQuery(searchVo).forEach(fcq -> {
                fcq.setUpdateTime(new Date());
                fcq.setUpdateId(LoginCache.get().getUsername());
                fcq.setIsQueryShow(formConfigQuery.getIsQueryShow());
                formConfigRepo.updateFormConfigQuery(fcq);
            });
            return;
        }
        FormConfigExt.FormConfig formConfig = map2Oject(formData.getData(), FormConfigExt.FormConfig.class);
        if (formConfig.empty()) {
            return;
        }
        ids.forEach(id -> {
            FormConfigQuery formConfigQuery = formConfigRepo.getFormConfigQuery(Long.valueOf(id));
            FormConfigExt formConfigExt = getFormConfigExt(formConfigQuery.getExt());
            if (formConfigExt == null) {
                formConfigExt = new FormConfigExt();
                formConfigExt.setForm(formConfig);
            } else {
                if (formConfigExt.getForm() == null) {
                    formConfigExt.setForm(formConfig);
                } else {
                    if (formConfig.getConfigCtr() != null) {
                        formConfigExt.getForm().setConfigCtr(formConfig.getConfigCtr());
                    }
                    formConfigExt.getForm().setLabelAlign(formConfig.getLabelAlign());
                    formConfigExt.getForm().setLabelWidth(formConfig.getLabelWidth());
                }
            }
            formConfigQuery.setExt(object2json(formConfigExt));
            formConfigQuery.setUpdateTime(new Date());
            formConfigQuery.setUpdateId(LoginCache.get().getUsername());
            formConfigRepo.updateFormConfigQuery(formConfigQuery);
        });
    }

    private boolean containColumn(DataModel dataModel, String column) {
        String master = dataModel.getMaster();
        String ds = dataModel.getDs();
        String dsKey = DataSourceContextHolder.getDataSourceKey();
        DataSourceContextHolder.checkDataSourceKey(ds);
        try {
            return dataSourceRepo.getColumns(master).containsKey(column);
        } finally {
            DataSourceContextHolder.setDataSourceKey(dsKey);
        }
    }

    interface QueryConfigCallback {
        Paging<FormConfigQueryVo> list(DataModel dataModel, Long formId, String name);
    }


    interface SaveFormQueryConfigCallback {
        void handleExt(FormConfigExt.FormConfigCtr formConfigCtr, FormConfigExt existFormConfigExt, FormConfigQuery formConfigQuery, FormConfigQuery existFormConfigQuery);
    }

    @Data
    static class QueryRet {
        Paging<FormConfigQueryVo> data;
        boolean init;
        String warning;
        Boolean formStatic;
    }
}